package com.platform.activiti.service;


import com.platform.HelperClazz;
import com.platform.activiti.dto.*;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.IdentityLinkType;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;


@Service
@Transactional
public class EasyActService {
    private Logger log = LogManager.getLogger(EasyActService.class);//日志文件

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private FormService formService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private JdbcTemplate jdbcTemplate;


    /*
     *
     * @author 王玉涛
     * @Date 2017/12/31 15:14
     * @param
     * @return
     */
    public int updateVar(String assignee, String taskId) {
        String key = this.findBuniness_keyByTaskId(taskId);
        String sql = " SELECT EXECUTION_ID_ FROM `act_ru_variable` WHERE TEXT_ ='" + key + "'";
        String EXECUTION_ID_ = jdbcTemplate.queryForObject(sql, String.class);

        sql = " UPDATE act_ru_variable set TEXT_='" + assignee + "' WHERE NAME_='assignee' AND EXECUTION_ID_ = '" + EXECUTION_ID_ + "'";
        int i = jdbcTemplate.update(sql);
        return i;
    }

    /***
     * 上传文件 用@RequestParam注解来指定表单上的file为MultipartFile
     *
     * @param file
     * @return
     */
    public String fileUpload(MultipartFile file) {
        // 判断文件是否为空
        if (!file.isEmpty()) {
            try {
                // 文件保存路径
                String path = HelperClazz.UPLOAD_PATH + file.getOriginalFilename();
                //上传
                file.transferTo(new File(path));
//            String fileName = file.getOriginalFilename();
//			 request.setAttribute("fileName", fileName);
                return path;

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 重定向
        return null;
    }

    /**
     * 部署流程定义
     */
    @Transactional
    public void saveNewDeploye(File file, String filename) {
        try {
            // 2：将File类型的文件转化成ZipInputStream流
            ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(file));
            repositoryService.createDeployment()// 创建部署对象
                    .name(filename)// 添加部署名称
                    .addZipInputStream(zipInputStream)//
                    .deploy();// 完成部署
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询部署对象信息，对应表（act_re_deployment）
     */

    public List<DeploymentBean> findDeploymentList() {
//        List<Deployment> depList = repositoryService.createDeploymentQuery()// 创建部署对象查询
//                .orderByDeploymenTime().desc()
//                .listPage(page, pageSize);
        List<Deployment> depList = repositoryService.createDeploymentQuery()// 创建部署对象查询
                .orderByDeploymenTime().asc()
                .list();
        List<DeploymentBean> list = new ArrayList<>();
        for (Deployment d : depList) {
            DeploymentBean deployment = new DeploymentBean();
            deployment.setId(d.getId());
            deployment.setName(d.getName());
            deployment.setDeployTime(d.getDeploymentTime());
            deployment.setCategory(d.getCategory());
            deployment.setTenantId(d.getTenantId());
            deployment.setTotalElements(depList.size());
            list.add(deployment);
        }
        return list;
    }


    /**
     * 查询流程定义的信息，对应表（act_re_procdef）
     */

    public List<ProcessDefinitionBean> findProcessDefinitionList(Integer page, Integer pageSize) {
        List<ProcessDefinition> pdList = repositoryService.createProcessDefinitionQuery()// 创建流程定义查询
                .orderByProcessDefinitionVersion().desc()//
                .listPage(page, pageSize);
        List<ProcessDefinition> pdList1 = repositoryService.createProcessDefinitionQuery()// 创建流程定义查询
                .orderByProcessDefinitionVersion().desc()//
                .list();
        List<ProcessDefinitionBean> list = new ArrayList<>();
        for (ProcessDefinition p : pdList) {
            ProcessDefinitionBean pd = new ProcessDefinitionBean();
            pd.setId(p.getId());
            pd.setName(p.getName());
            pd.setKey(p.getKey());
            pd.setVersion(p.getVersion());
            pd.setCategory(p.getCategory());
            pd.setTenantId(p.getTenantId());
            pd.setTotalElements(pdList1.size());
            list.add(pd);
        }
        return list;
    }

    /**
     * 使用部署对象ID和资源图片名称，获取图片的输入流
     */

    public InputStream findImageInputStream(String deploymentId, String imageName) {
        return repositoryService.getResourceAsStream(deploymentId, imageName);
    }

    /**
     * 使用部署对象ID，删除流程定义
     */
    @Transactional
    public void deleteProcessDefinitionByDeploymentId(String deploymentId) {
        repositoryService.deleteDeployment(deploymentId, true);
    }

    /**
     * 启动流程实例，让启动的流程实例关联业务
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/22 13:56
     */
    @Transactional
    public void saveStartProcess(String key, String objId, Map<String, Object> variables) {

        /**
         (1)使用流程变量设置字符串（格式：LeaveBill.id的形式），通过设置，让启动的流程（流程实例）关联业务
         (2)使用正在执行对象表中的一个字段BUSINESS_KEY（Activiti提供的一个字段），让启动的流程（流程实例）关联业务
         */
        //格式：LeaveBill.id的形式（使用流程变量）
        objId = key + "." + objId;
        variables.put("objId", objId);
        //使用流程定义的key，启动流程实例，同时设置流程变量，同时向正在执行的执行对象表中的字段BUSINESS_KEY添加业务数据，同时让流程关联业务
        runtimeService.startProcessInstanceByKey(key, objId, variables);

    }

    /**
     * 设置任务执行人
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/23 10:29
     */
    public void setAssigneeTask(Task task) {//指定的办理人

        Map<String, Object> variables = new HashMap<>();
        taskService.setVariables(task.getId(), variables);
    }

    /**
     * 查询正在执行的任务表，获取当前个人任务的集合List<Task>
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/23 19:45
     */

    public String findTaskListByUserId(String assignee) {//name为task表中Assignee的值
        String sql ="SELECT GROUP_CONCAT(e.k, ',0') id\n" +
                "FROM\n" +
                "\t(\n" +
                "\t\tSELECT DISTINCT\n" +
                "\t\t\tCONCAT(\n" +
                "\t\t\t\t\"'\",\n" +
                "\t\t\t\tSUBSTRING_INDEX(e.BUSINESS_KEY_, '.', - 1),\n" +
                "\t\t\t\t\"'\"\n" +
                "\t\t\t) k\n" +
                "\t\tFROM\n" +
                "\t\t\t`act_ru_task` t\n" +
                "\t\tLEFT JOIN act_ru_execution e ON t.EXECUTION_ID_ = e.ID_\n" +
                "\t\tWHERE\n" +
                "\t\t\tt.ASSIGNEE_ = '"+assignee+"' ) e";
        Task task = taskService//
                .createNativeTaskQuery()
                .sql(sql)//
                .singleResult();
        return task.getId();
    }
    /**
     * 查询正在执行的任务表，获取当前个人任务的集合List<Task>
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/23 19:45
     */

    public List<TaskBean> findTaskList(String assignee) {//name为task表中Assignee的值
        List<Task> list1 = taskService.createTaskQuery()//
                .taskAssignee(assignee)//指定个人任务查询
                .orderByTaskCreateTime().desc()//
                .list();

        List<TaskBean> list = new ArrayList<>();
        for (Task t : list1) {
            List<String> outComeList = this.findOutComeListByTaskId(t.getId());//下一步连线
            TaskBean tb = new TaskBean();
            tb.setTaskId(t.getId());
            String buniness_key = this.findBuniness_keyByTaskId(t.getId());
            //5：获取BUSINESS_KEY对应的主键ID，使用主键ID，查询事件对象（Yj_event.1）
            String id = "";
            if (StringUtils.isNotBlank(buniness_key)) {
                //截取字符串，取buniness_key小数点的第2个值
                id = buniness_key.split("\\.")[1];
            }
            tb.setId(id);
            tb.setOutcomeList(outComeList);
            list.add(tb);
        }
        return list;
    }

    /**
     * 查询正在执行的任务表，获取当前个人任务的集合List<Task>
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/23 19:45
     */

    public String findTask(String objectId, String objectName, String assignee) {//name为task表中Assignee的值

        //组织流程表中的字段中的值
        String objId = objectName + "." + objectId;

        /**1:使用历史的流程实例查询，返回历史的流程实例对象，获取流程实例ID*/
        List<Task> taskList = taskService.createTaskQuery()
                .processInstanceBusinessKey(objId)
                .taskAssignee(assignee)
                .list();
        String taskId = "";
        if (taskList.size() > 0) {
            taskId = taskList.get(0).getId();
        }

        return taskId;
    }

    /**
     * 查询历史任务表，获取当前个人任务的集合List<Task>
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/23 19:45
     */

    public List<String> findHisTaskList(String assignee) {//name为task表中Assignee的值
        List<HistoricTaskInstance> list1 = historyService.createHistoricTaskInstanceQuery()
                .taskAssignee(assignee)//指定个人任务查询
                .orderByTaskCreateTime().desc()//
                .list();
        List<String> list = new ArrayList<>();
        for (HistoricTaskInstance t : list1) {
            String buniness_key = this.findBuniness_keyByProcessInstanceId(t.getProcessInstanceId());
            //5：获取BUSINESS_KEY对应的主键ID，使用主键ID，查询事件对象（Yj_event.1）
            String id = "";
            if (StringUtils.isNotBlank(buniness_key)) {
                //截取字符串，取buniness_key小数点的第2个值
                id = buniness_key.split("\\.")[1];
            }
            list.add(id);
        }
        return list;
    }

    /*
     *  通过taskid 查询流程定义id
     * @author 王玉涛
     * @Date 2018/3/12 17:18
     * @param
     * @return
     */
    public String getPdidnByTaskId(String taskId) {
        // 1. 得到task
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        // 2. 通过task对象的pdid获取流程定义对象
        ProcessDefinition pd = repositoryService.getProcessDefinition(task.getProcessDefinitionId());
        return pd.getId();
    }

    /*
     * 通过流程定义id，查询最新的taskid
     * @author 王玉涛
     * @Date 2018/3/12 17:18
     * @param
     * @return
     */
    public String getTaskIdByPdid(String pdid) {
        // 1. 得到task
        Task task = taskService.createTaskQuery().processDefinitionId(pdid).orderByTaskCreateTime().desc().list().get(0);
        return task.getId();
    }

    /*
     *
     * @author 王玉涛
     * @Date 2017/12/31 15:14
     * @param
     * @return
     */
    public String getTaskIdByExecutionId(String executionId) {
        Task task = taskService.createTaskQuery().executionId(executionId).singleResult();
        return task.getId();
    }

    /*
     *
     * @author 王玉涛
     * @Date 2017/12/31 15:14
     * @param
     * @return
     */
    public int updateIdentitylink(String assignee, String taskId) {
        String sql = " UPDATE `act_ru_identitylink` SET USER_ID_='" + assignee + "' WHERE TASK_ID_='" + taskId + "'";

//        sql = " UPDATE act_ru_variable set TEXT_='" + assignee + "' WHERE NAME_='assignee' AND EXECUTION_ID_ = '" + EXECUTION_ID_ + "'";
        int i = jdbcTemplate.update(sql);
        return i;
    }
    /**
     * 使用流程实例ID，查询任务id
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/25 21:10
     */
    public boolean findTaskIdInExOnlyOne(String executionId) {
        boolean flag = false;
        List<Task> task = taskService.createTaskQuery().executionId(executionId).list();
        /**1:使用历史的流程实例查询，返回历史的流程实例对象，获取流程实例ID*/
        if (task.size() == 1) {
            flag = true;
        }
        return flag;
    }
    /**
     * 查询正在执行的任务表，获取当前组任务的集合List<Task>
     * Created by 王玉涛
     *
     * @param assignee
     * @Param
     * @date 2017/6/23 19:45
     */
    public List<TaskBean> findGroupList(String assignee) {
        String sql = "SELECT  t.ID_ FROM ACT_RU_TASK t LEFT JOIN ACT_RU_IDENTITYLINK i ON t.ID_=i.TASK_ID_ WHERE i.TYPE_='candidate' AND ISNULL(t.ASSIGNEE_) AND i.USER_ID_ IN (" + assignee + ")  ORDER BY t.CREATE_TIME_ DESC";
        String sql2 = "SELECT COUNT(t.ID_) FROM ACT_RU_TASK t LEFT JOIN ACT_RU_IDENTITYLINK i ON t.ID_=i.TASK_ID_ WHERE i.TYPE_='candidate' AND ISNULL(t.ASSIGNEE_) AND i.USER_ID_ IN (" + assignee + ")  ORDER BY t.CREATE_TIME_ DESC";
        List<Task> list1 = taskService//
                .createNativeTaskQuery()
                .sql(sql)//
                .list();

        int count = (int) taskService.createNativeTaskQuery()
                .sql(sql2)//
                .count();
        List<TaskBean> list = new ArrayList<>();
        for (Task t : list1) {
            TaskBean tb = new TaskBean();
            tb.setTaskId(t.getId());
            String buniness_key = this.findBuniness_keyByTaskId(t.getId());
            //5：获取BUSINESS_KEY对应的主键ID，使用主键ID，查询事件对象（Yj_event.1）
            String id = "";
            if (StringUtils.isNotBlank(buniness_key)) {
                //截取字符串，取buniness_key小数点的第2个值
                id = buniness_key.split("\\.")[1];
            }
            tb.setId(id);
            tb.setTotalElements(count);
            list.add(tb);
        }
        return list;
    }

    /**
     * 将组任务分配给个人任务，领取任务
     * 由1个人去完成任务
     * Created by 王玉涛
     *
     * @Param String taskId, String userId
     * @date 2017/6/23 22:14
     */
    public void claim(String taskId, String userId) {//任务ID,分配的办理人
        taskService.claim(taskId, userId);
    }

    /**
     * 回退个人任务为组任务
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/23 22:53
     */
    public void rollbackGroup(String taskId) {//任务ID,分配的办理人
        taskService.setAssignee(taskId, null);
    }

    /**
     * 添加处理意见
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/22 20:55
     */
    public void commentAdd(Task task, ProcessInstance pi) {
        // 查找任务
        task = taskService.createTaskQuery().processInstanceId(pi.getId())
                .singleResult();
        // 添加任务评论
        taskService.addComment(task.getId(), pi.getId(), "this is comment message");
    }

    /**
     * 查询处理意见
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/22 21:02
     */
//    public List<Comment> findComment(Task task) {
//        return taskService.getTaskComments(task.getId());
//    }

    /**
     * 使用任务ID，查找事件ID，从而获取事件信息
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/24 23:31
     */
    public String findBuniness_keyByTaskId(String taskId) {
        //1：使用任务ID，查询任务对象Task
        Task task = taskService.createTaskQuery()//
                .taskId(taskId)//使用任务ID查询
                .singleResult();
        //2：使用任务对象Task获取流程实例ID
        String processInstanceId = task.getProcessInstanceId();
        //3：使用流程实例ID，查询正在执行的执行对象表，返回流程实例对象
        ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
                .processInstanceId(processInstanceId)//使用流程实例ID查询
                .singleResult();
        //4：使用流程实例对象获取BUSINESS_KEY
        String buniness_key = pi.getBusinessKey();
        return buniness_key;
    }

    /**
     * 使用流程实例ID，查找事件ID，从而获取事件信息
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/24 23:31
     */
    public String findBuniness_keyByProcessInstanceId(String processInstanceId) {
        //3：使用流程实例ID，查询历史的执行对象表，返回历史流程实例对象
        HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery()//
                .processInstanceId(processInstanceId)//使用流程实例ID查询
                .singleResult();
        //4：使用流程实例对象获取BUSINESS_KEY
        String buniness_key = "";
        if (pi != null) {
            buniness_key = pi.getBusinessKey();
        }
        return buniness_key;
    }

    /**
     * 查询历史任务
     *
     * @author 王玉涛
     * @Param
     * @date 2017-09-05 15:44
     */
    public String historyTaskList(String userId) {
        List<HistoricTaskInstance> list = historyService // 历史任务Service
                .createHistoricTaskInstanceQuery() // 创建历史任务实例查询
                .taskAssignee(userId) // 指定办理人
                .finished() // 查询已经完成的任务
                .list();
        String key = "";
        for (HistoricTaskInstance task : list) {
            //2：使用任务对象Task获取流程实例ID
            String processInstanceId = task.getProcessInstanceId();
            //3：使用流程实例ID，查询正在执行的执行对象表，返回流程实例对象
            HistoricProcessInstance hpi = historyService // 历史任务Service
                    .createHistoricProcessInstanceQuery() // 创建历史流程实例查询
                    .processInstanceId(processInstanceId) // 指定流程实例ID
                    .singleResult();
            //4：使用流程实例对象获取BUSINESS_KEY
            String buniness_key = hpi.getBusinessKey();
            if (StringUtils.isNotBlank(buniness_key)) {
                //截取字符串，取buniness_key小数点的第2个值
                buniness_key = buniness_key.split("\\.")[1];
            }
            key += buniness_key + ",";
        }
        key = key.substring(0, key.length() - 1);
        return key;
    }

    /**
     * 使用任务id查询事件信息，和下一步连线,用于指定功能按钮
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/24 23:32
     */
    public Map<String, Object> findEvent(String taskId) {
        Map<String, Object> map = new HashMap<>();
        //使用任务id查询业务id
        String buniness_key = this.findBuniness_keyByTaskId(taskId);
        //5：获取BUSINESS_KEY对应的主键ID，使用主键ID，查询业务对象（YjEvent.1）
        String id = "";
        if (StringUtils.isNotBlank(buniness_key)) {
            //截取字符串，取buniness_key小数点的第2个值
            id = buniness_key.split("\\.")[1];
        }
        List<Comment> list = this.findCommentByTaskId(taskId);//查询任务的历史处理意见
        List<String> outComeListByTaskId = new ArrayList<>();
        try {
            outComeListByTaskId = this.findOutComeListByTaskId(taskId);//下一步连线
        } catch (Exception e) {
            outComeListByTaskId.add("无下一步信息");
        }
        map.put("outComeList", outComeListByTaskId);
        map.put("commentList", list);
        map.put("id", id);
        return map;
    }

    /**
     * 已知任务ID，查询ProcessDefinitionEntiy对象，从而获取当前任务完成之后的连线名称，并放置到List<String>集合中
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/25 13:31
     */

    public List<String> findOutComeListByTaskId(String taskId) {
        //返回存放连线的名称集合
        List<String> list = new ArrayList<String>();
        //1:使用任务ID，查询任务对象
        Task task = taskService.createTaskQuery()//
                .taskId(taskId)//使用任务ID查询
                .singleResult();
        //2：获取流程定义ID
        String processDefinitionId = task.getProcessDefinitionId();

        //3：查询ProcessDefinitionEntiy对象
        ProcessDefinitionEntity processDefinitionEntity =
                (ProcessDefinitionEntity)
                        repositoryService.getProcessDefinition(processDefinitionId);
        //使用任务对象Task获取流程实例ID
        String processInstanceId = task.getProcessInstanceId();
        //使用流程实例ID，查询正在执行的执行对象表，返回流程实例对象
        ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
                .processInstanceId(processInstanceId)//使用流程实例ID查询
                .singleResult();
        //获取当前活动的id
        String activityId = pi.getActivityId();
        String key = task.getTaskDefinitionKey();
        if (null == activityId) {
            activityId = key;
        }
        //4：获取当前的活动
        ActivityImpl activityImpl =
                processDefinitionEntity.findActivity(activityId);
        //5：获取当前活动完成之后连线的名称
        List<PvmTransition> pvmList = activityImpl.getOutgoingTransitions();
        if (pvmList != null && pvmList.size() > 0) {
            for (PvmTransition pvm : pvmList) {
                String name = (String) pvm.getProperty("name");
                if (StringUtils.isNotBlank(name)) {
                    list.add(name);
                } else {
                    list.add("默认提交");
                }
            }
        }
        return list;
    }

    /**
     * 添加批注
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/25 18:27
     */
    public void addComment(WorkFlow workFlow) {
        //获取任务ID
        String taskId = workFlow.getTaskId();
        //批注信息
        String message = workFlow.getComment();

        String name = workFlow.getUserMassage();

        /**
         * 1：在完成之前，添加一个批注信息，向act_hi_comment表中添加数据，用于记录对当前申请人的一些审核信息
         */
        //使用任务ID，查询任务对象，获取流程流程实例ID
        Task task = taskService.createTaskQuery()//
                .taskId(taskId)//使用任务ID查询
                .singleResult();
        //获取流程实例ID
        String processInstanceId = task.getProcessInstanceId();
        /**
         *
         * 注意：添加批注的时候，由于Activiti底层代码是使用：
         * String userId = Authentication.getAuthenticatedUserId();
         CommentEntity comment = new CommentEntity();
         comment.setUserId(userId);
         所有需要从Session中获取当前登录人，作为该任务的办理人（审核人），对应act_hi_comment表中的User_ID的字段，不过不添加审核人，该字段为null
         所以要求，添加配置执行使用Authentication.setAuthenticatedUserId();添加当前任务的审核人
         * */
        Authentication.setAuthenticatedUserId(name);
        taskService.addComment(taskId, processInstanceId, message);
    }


    /**
     * 指定连线的名称完成任务
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/25 18:27
     */
    public void saveSubmitTask(WorkFlow workFlow, Map<String, Object> variables) {
        //获取任务ID
        String taskId = workFlow.getTaskId();
        //获取连线的名称
        String outcome = workFlow.getOutcome();
        //获取事件ID
        String id = workFlow.getId();
        //使用任务ID，查询任务对象，获取流程流程实例ID
//        Task task = taskService.createTaskQuery()//
//                .taskId(taskId)//使用任务ID查询
//                .singleResult();
        //获取流程实例ID
//        String processInstanceId = task.getProcessInstanceId();
        /**
         * 2：如果连线的名称是“默认提交”，那么就不需要设置，如果不是，就需要设置流程变量
         * 在完成任务之前，设置流程变量，按照连线的名称，去完成任务
         流程变量的名称：outcome
         流程变量的值：连线的名称
         */
        if (outcome != null && !outcome.equals("")) {
            variables.put("outcome", outcome);
        }

        //3：使用任务ID，完成当前人的个人任务，同时流程变量
        taskService.complete(taskId, variables);
        //4：当任务完成之后，需要指定下一个任务的办理人（使用流程变量）

        /**
         * 5：在完成任务之后，判断流程是否结束
         如果流程结束了，更新事件表的状态从1变成2（审核中-->审核完成）
         */
//        ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
//                .processInstanceId(processInstanceId)//使用流程实例ID查询
//                .singleResult();
        //流程结束了
//        if (pi == null) {
//            //更新事件表的状态从1变成2（审核中-->审核完成）
////            CgEvent yj = yjEventService.findLeaveBillById(id);
////            yj.setState(2);
//            return true;
//        }
//        return false;
    }

    /**
     * 获取批注信息，传递的是当前任务ID，获取历史任务ID对应的批注
     */

    public List<Comment> findCommentByTaskId(String taskId) {
        List<Comment> list = new ArrayList<Comment>();
        //使用当前的任务ID，查询当前流程对应的历史任务ID
        //使用当前任务ID，获取当前任务对象
        Task task = taskService.createTaskQuery()//
                .taskId(taskId)//使用任务ID查询
                .singleResult();
        //获取流程实例ID
        String processInstanceId = task.getProcessInstanceId();
        // //使用流程实例ID，查询历史任务，获取历史任务对应的每个任务ID
        List<HistoricTaskInstance> htiList =
                historyService.createHistoricTaskInstanceQuery()//历史任务表查询
                        .processInstanceId(processInstanceId)//使用流程实例ID查询
                        .list();
        //遍历集合，获取每个任务ID
        if (htiList != null && htiList.size() > 0) {
            for (HistoricTaskInstance hti : htiList) {
                //任务ID
                String htaskId = hti.getId();
                //获取批注信息
                List<Comment> taskList =
                        taskService.getTaskComments(htaskId);//对用历史完成后的任务ID
                list.addAll(taskList);
            }
        }
        list = taskService.getProcessInstanceComments(processInstanceId);
        return list;
    }


    /**
     * 使用对象ID，查询历史意见信息
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/25 21:10
     */
    public List<Comment> findCommentByObjecId(String objectName, String id) {

        //组织流程表中的字段中的值
        String objId = objectName + "." + id;

        /**1:使用历史的流程实例查询，返回历史的流程实例对象，获取流程实例ID*/
//        HistoricProcessInstance hpi =
//                historyService.createHistoricProcessInstanceQuery()//对应历史的流程实例表
//                        .processInstanceBusinessKey(objId)//使用BusinessKey字段查询
//                        .singleResult();
        List<HistoricProcessInstance> hpi =
                historyService.createHistoricProcessInstanceQuery()//对应历史的流程实例表
                        .processInstanceBusinessKey(objId)//使用BusinessKey字段查询
                        .list();
        //流程实例ID
        String processInstanceId = "";
        if (hpi.size() > 0) {
            processInstanceId = hpi.get(0).getId();
        }
        /**2:使用历史的流程变量查询，返回历史的流程变量的对象，获取流程实例ID*/
//        HistoricVariableInstance hvi =
//                historyService.createHistoricVariableInstanceQuery()//对应历史的流程变量表
//                        .variableValueEquals("objId", objId)//使用流程变量的名称和流程变量的值查询
//                        .singleResult();
        //流程实例ID
//        String processInstanceId = hvi.getProcessInstanceId();
        List<Comment> list1 =
                taskService.getProcessInstanceComments(processInstanceId);
        List<CommentBean> list = new ArrayList<>();
        for (Comment c : list1) {
            CommentBean cb = new CommentBean();
            cb.setFullMessage(c.getFullMessage());
            cb.setId(c.getId());
            cb.setProcessInstanceId(c.getProcessInstanceId());
            cb.setTaskId(c.getTaskId());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
            String str = sdf.format(c.getTime());
            cb.setTime(str);
            cb.setType(c.getType());
            cb.setUserId(c.getUserId());
            list.add(cb);
        }
        return list1;
    }

    public void test(String id) {
        taskService.deleteGroupIdentityLink(id, id, IdentityLinkType.ASSIGNEE);
    }

    /**
     * 1：获取任务ID，获取任务对象，使用任务对象获取流程定义ID，查询流程定义对象
     */

    public ProcessDefinition findProcessDefinitionByTaskId(String taskId) {
        //使用任务ID，查询任务对象
        Task task = taskService.createTaskQuery()//
                .taskId(taskId)//使用任务ID查询
                .singleResult();
        //获取流程定义ID
        String processDefinitionId = task.getProcessDefinitionId();
        //查询流程定义的对象
        ProcessDefinition pd =
                repositoryService.createProcessDefinitionQuery()//创建流程定义查询对象，对应表act_re_procdef
                        .processDefinitionId(processDefinitionId)//使用流程定义ID查询
                        .singleResult();
        return pd;
    }

    /**
     * 二：查看当前活动，获取当期活动对应的坐标x,y,width,height，将4个值存放到Map<String,Object>中
     * map集合的key：表示坐标x,y,width,height
     * map集合的value：表示坐标对应的值
     */

    public Map<String, Object> findCoordingByTask(String taskId) {
        //存放坐标
        Map<String, Object> map = new HashMap<String, Object>();
        //使用任务ID，查询任务对象
        Task task = taskService.createTaskQuery()//
                .taskId(taskId)//使用任务ID查询
                .singleResult();
        //获取流程定义的ID
        String processDefinitionId = task.getProcessDefinitionId();
        //获取流程定义的实体对象（对应.bpmn文件中的数据）
        ProcessDefinitionEntity processDefinitionEntity =
                (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
        //流程实例ID
        String processInstanceId = task.getProcessInstanceId();
        //使用流程实例ID，查询正在执行的执行对象表，获取当前活动对应的流程实例对象
        ProcessInstance pi =
                runtimeService.createProcessInstanceQuery()//创建流程实例查询
                        .processInstanceId(processInstanceId)//使用流程实例ID查询
                        .singleResult();
        //获取当前活动的ID
        String activityId = pi.getActivityId();
        String key = task.getTaskDefinitionKey();
        if (null == activityId) {
            activityId = key;
        }
        //获取当前活动对象
        ActivityImpl activityImpl =
                processDefinitionEntity.findActivity(activityId);//活动ID
        //获取坐标
        map.put("x", activityImpl.getX());
        map.put("y", activityImpl.getY());
        map.put("width", activityImpl.getWidth());
        map.put("height", activityImpl.getHeight());
        return map;
    }

    /**
     * 退回上一个节点
     *
     * @author 王玉涛
     * @Param
     * @date 2017/7/25 22:42
     */

    public String rollBackAct(String taskId) {

        try {
            Map<String, Object> variables;
            // 取得当前任务.当前任务节点
            HistoricTaskInstance currTask = historyService
                    .createHistoricTaskInstanceQuery().taskId(taskId)
                    .singleResult();
            // 取得流程实例，流程实例
            ProcessInstance instance = runtimeService
                    .createProcessInstanceQuery()
                    .processInstanceId(currTask.getProcessInstanceId())
                    .singleResult();
            if (instance == null) {
                log.info("流程结束");
                log.error("出错啦！流程已经结束");
                return "ERROR";
            }
            variables = instance.getProcessVariables();
            // 取得流程定义
            ProcessDefinitionEntity definition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                    .getDeployedProcessDefinition(currTask
                            .getProcessDefinitionId());
            if (definition == null) {
                log.info("流程定义未找到");
                log.error("出错啦！流程定义未找到");
                return "ERROR";
            }
            // 取得上一步活动
            ActivityImpl currActivity = ((ProcessDefinitionImpl) definition)
                    .findActivity(currTask.getTaskDefinitionKey());

            //也就是节点间的连线
            List<PvmTransition> nextTransitionList = currActivity
                    .getIncomingTransitions();
            // 清除当前活动的出口
            List<PvmTransition> oriPvmTransitionList = new ArrayList<PvmTransition>();
            //新建一个节点连线关系集合

            List<PvmTransition> pvmTransitionList = currActivity
                    .getOutgoingTransitions();
            //
            for (PvmTransition pvmTransition : pvmTransitionList) {
                oriPvmTransitionList.add(pvmTransition);
            }
            pvmTransitionList.clear();

            // 建立新出口
            List<TransitionImpl> newTransitions = new ArrayList<TransitionImpl>();
            for (PvmTransition nextTransition : nextTransitionList) {
                PvmActivity nextActivity = nextTransition.getSource();
                ActivityImpl nextActivityImpl = ((ProcessDefinitionImpl) definition)
                        .findActivity(nextActivity.getId());
                TransitionImpl newTransition = currActivity
                        .createOutgoingTransition();
                newTransition.setDestination(nextActivityImpl);
                newTransitions.add(newTransition);
            }
            // 完成任务
            List<Task> tasks = taskService.createTaskQuery()
                    .processInstanceId(instance.getId())
                    .taskDefinitionKey(currTask.getTaskDefinitionKey()).list();
            for (Task task : tasks) {
                taskService.complete(task.getId(), variables);
                historyService.deleteHistoricTaskInstance(task.getId());
            }
            // 恢复方向
            for (TransitionImpl transitionImpl : newTransitions) {
                currActivity.getOutgoingTransitions().remove(transitionImpl);
            }
            for (PvmTransition pvmTransition : oriPvmTransitionList) {
                pvmTransitionList.add(pvmTransition);
            }
            log.info("OK");
            log.info("流程结束");

            return "SUCCESS";
        } catch (Exception e) {
            log.error("失败");
            log.error(e.getMessage());
            return "ERROR";
        }
    }

    /**
     * 回退到指定节点
     *
     * @author 王玉涛
     * @Param
     * @date 2017/7/25 22:47
     */
    public String rollBackToAssignAct(String taskId, String destTaskkey) {
        try {
            Map<String, Object> variables;
            // 取得当前任务.当前任务节点
            HistoricTaskInstance currTask = historyService
                    .createHistoricTaskInstanceQuery().taskId(taskId)
                    .singleResult();
            // 取得流程实例，流程实例
            ProcessInstance instance = runtimeService
                    .createProcessInstanceQuery()
                    .processInstanceId(currTask.getProcessInstanceId())
                    .singleResult();
            if (instance == null) {
                log.info("流程结束");
                log.error("出错啦！流程已经结束");
                return "ERROR";
            }
            variables = instance.getProcessVariables();
            // 取得流程定义
            ProcessDefinitionEntity definition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                    .getDeployedProcessDefinition(currTask
                            .getProcessDefinitionId());
            if (definition == null) {
                log.info("流程定义未找到");
                log.error("出错啦！流程定义未找到");
                return "ERROR";
            }
            //取得当前活动节点
            ActivityImpl currActivity = ((ProcessDefinitionImpl) definition)
                    .findActivity(currTask.getTaskDefinitionKey());

            log.info("currActivity" + currActivity);
            // 取得上一步活动
            //也就是节点间的连线
            //获取来源节点的关系
            List<PvmTransition> nextTransitionList = currActivity.getIncomingTransitions();

            // 清除当前活动的出口
            List<PvmTransition> oriPvmTransitionList = new ArrayList<PvmTransition>();
            //新建一个节点连线关系集合
            //获取出口节点的关系
            List<PvmTransition> pvmTransitionList = currActivity
                    .getOutgoingTransitions();
            //
            for (PvmTransition pvmTransition : pvmTransitionList) {
                oriPvmTransitionList.add(pvmTransition);
            }
            pvmTransitionList.clear();

            // 建立新出口
            List<TransitionImpl> newTransitions = new ArrayList<TransitionImpl>();
            for (PvmTransition nextTransition : nextTransitionList) {
                PvmActivity nextActivity = nextTransition.getSource();

                log.info("nextActivity" + nextActivity);

                log.info("nextActivity.getId()" + nextActivity.getId());

                //destTaskkey
                ActivityImpl nextActivityImpl = ((ProcessDefinitionImpl) definition)
                        // .findActivity(nextActivity.getId());
                        .findActivity(destTaskkey);
                TransitionImpl newTransition = currActivity
                        .createOutgoingTransition();
                newTransition.setDestination(nextActivityImpl);
                newTransitions.add(newTransition);
            }
            // 完成任务
            List<Task> tasks = taskService.createTaskQuery()
                    .processInstanceId(instance.getId())
                    .taskDefinitionKey(currTask.getTaskDefinitionKey()).list();
            for (Task task : tasks) {
                taskService.complete(task.getId(), variables);
                historyService.deleteHistoricTaskInstance(task.getId());
            }
            // 恢复方向
            for (TransitionImpl transitionImpl : newTransitions) {
                currActivity.getOutgoingTransitions().remove(transitionImpl);
            }
            for (PvmTransition pvmTransition : oriPvmTransitionList) {

                pvmTransitionList.add(pvmTransition);
            }
            log.info("OK");
            log.info("流程结束");

            return "SUCCESS";
        } catch (Exception e) {
            log.error("失败");
            log.error(e.getMessage());
            return "ERROR";
        }
    }

    /**
     * 删除流流程实例
     *
     * @author 王玉涛
     * @Param
     * @date 2017-11-17 13:36
     */
    public String deleteProcessInstance(String taskId) {
        try {
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            String processID = task.getProcessInstanceId();
            runtimeService.deleteProcessInstance(processID, "删除测试");
        } catch (Exception e) {
            return "删除失败，没有该任务";
        }
        return "删除成功";
    }

    public ProcessDefinition getProcessDefinitionByTaskId(String taskId) {
        // 1. 得到task
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        // 2. 通过task对象的pdid获取流程定义对象
        ProcessDefinition pd = repositoryService.getProcessDefinition(task.getProcessDefinitionId());
        return pd;
    }

    public ProcessDefinition getProcessDefinitionById(String id) {
        // 通过task对象的pdid获取流程定义对象
        ProcessDefinition pd = repositoryService.getProcessDefinition(id);
        return pd;
    }

    public ProcessDefinition getProcessDefinitionByDepId(String id) {
        // 通过task对象的pdid获取流程定义对象
        ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                .deploymentId(id)
                .singleResult();
        return pd;
    }

    public void completeTask(WorkFlow workFlow, Map<String, Object> variables) {
        this.addComment(workFlow);
        this.saveSubmitTask(workFlow, variables);
    }

    /**
     * 使用对象ID，查询任务id
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/25 21:10
     */
    public String findTaskIdByObjecId(String objectName, String id) {

        //组织流程表中的字段中的值
        String objId = objectName + "." + id;

        /**1:使用历史的流程实例查询，返回历史的流程实例对象，获取流程实例ID*/
        List<Task> task = taskService.createTaskQuery()
                .processInstanceBusinessKey(objId)
                .orderByTaskCreateTime().desc()
                .list();
        if (task.size() > 0) {
            String taskId = task.get(0).getId();
            return taskId;

        } else
            return null;

    }

    /**
     * 使用对象ID，查询任务id,无办理人
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/25 21:10
     */
    public String findTaskIdByObjecIdAndAssigneeIsNull(String objectName, String id, String roleids) {

        //组织流程表中的字段中的值
        String objId = objectName + "." + id;

        /**1:使用历史的流程实例查询，返回历史的流程实例对象，获取流程实例ID*/
        List<Task> task = taskService.createTaskQuery()
                .processInstanceBusinessKey(objId)
                .taskUnassigned()
                .orderByTaskCreateTime().desc()
                .list();
        if (task.size() == 1) {
            String taskId = task.get(0).getId();
            return taskId;

        } else {
            Task task1 = taskService.createTaskQuery()
                    .taskUnassigned()
                    .processInstanceBusinessKey(objId)
                    .taskCandidateOrAssigned(roleids)
                    .singleResult();
            if (task1 != null) {
                return task1.getId();
            }
        }
        return null;

    }

    /**
     * 使用对象ID，查询当前节点办理人列表
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/25 21:10
     */
    public List<String> findAssigneeListByObjecId(String objectName, String id) {

        //组织流程表中的字段中的值
        String objId = objectName + "." + id;

        /**1:使用历史的流程实例查询，返回历史的流程实例对象，获取流程实例ID*/
        List<Task> taskList = taskService.createTaskQuery()
                .processInstanceBusinessKey(objId)
                .orderByTaskCreateTime().desc()
                .list();
        List<String> assignees = new ArrayList<>();
        for (Task t : taskList) {
            String assignee = t.getAssignee();
            if (StringUtils.isNotBlank(assignee))
                assignees.add(assignee);
        }
        return assignees;
    }

    /*
     *   根据节点和业务id查询办理部门的信息
     * @author 王玉涛  
     * @Date 2017/12/13 15:47
     * @param   
     * @return   
     */
    public List<String> getOrgs(String taskKey, String id, String objectName) {
        List<String> strings = new ArrayList<>();
        //组织流程表中的字段中的值
        String objId = objectName + "." + id;
        List<Task> taskList = taskService.createTaskQuery()
                .processInstanceBusinessKey(objId)
                .taskDefinitionKey(taskKey)
                .orderByTaskCreateTime().desc()
                .list();
        for (Task t : taskList) {
            List<IdentityLink> links = taskService.getIdentityLinksForTask(t.getId());
            for (IdentityLink link : links) {
                String orgId = link.getUserId();
                strings.add(orgId.split("\\.")[0]);
            }
        }
        return strings;
    }

    /*
     *  获取当前个人任务的业务id列表
     * @author 王玉涛
     * @Date 2017/12/13 15:47
     * @param
     * @return
     */
    public List<String> getTasksAndAssigneeNotnull() {
        List<String> strings = new ArrayList<>();
        //组织流程表中的字段中的值
        List<Task> taskList = taskService.createTaskQuery()
                .list();
        for (Task task : taskList) {
            if (task.getAssignee() != null) {
                String buniness_key = this.findBuniness_keyByTaskId(task.getId());
                //5：获取BUSINESS_KEY对应的主键ID，使用主键ID，查询业务对象（YjEvent.1）
                String id = "";
                if (StringUtils.isNotBlank(buniness_key)) {
                    //截取字符串，取buniness_key小数点的第2个值
                    id = buniness_key.split("\\.")[1];
                }
                strings.add(id);
            }
        }
        return strings;
    }

    /*
   *
   * @author 王玉涛
   * @Date 2017/12/13 15:47
   * @param
   * @return
   */
    public int getCount(String taskKey, String assignees) {
        String assigneess[] = assignees.split(",");
        //组织流程表中的字段中的值
        long counts = 0;
        int count = 0;
        for (String assignee : assigneess) {

            counts = historyService.createHistoricTaskInstanceQuery()//历史任务表查询
                    .taskAssignee(assignee)
                    .taskDefinitionKey(taskKey)
                    .count();
            count = count + (int) counts;

        }
        return count;
    }


    /**
     * 使用对象ID，查询任务id
     * Created by 王玉涛
     *
     * @Param
     * @date 2017/6/25 21:10
     */
    public boolean findTaskIdOnlyOne(String objectName, String taskId) {
        String buniness_key = this.findBuniness_keyByTaskId(taskId);
        //5：获取BUSINESS_KEY对应的主键ID，使用主键ID，查询业务对象（YjEvent.1）
        String objId = "";
        if (StringUtils.isNotBlank(buniness_key)) {
            //截取字符串，取buniness_key小数点的第2个值
            objId = buniness_key.split("\\.")[1];
        }
        boolean flag = false;
        //组织流程表中的字段中的值
        objId = objectName + "." + objId;

        /**1:使用历史的流程实例查询，返回历史的流程实例对象，获取流程实例ID*/
        List<Task> task = taskService.createTaskQuery()
                .processInstanceBusinessKey(objId)
                .orderByTaskCreateTime().desc()
                .list();
        if (task.size() == 1) {
            flag = true;
        }
        return flag;
    }
}
